#ifndef AFN_H
#define AFN_H
#include "IFn.h"
#include "Ref.h"

namespace clojure_lang {

template <class T, class E, class I>
class AFn
{
public:

    virtual CjObject *operator() ()
    {
        E *t = new E();
        return invoke(t);
    }

    virtual CjObject *operator() (CjObject *a)
    {
        T *t = new T(a);
        return invoke(t);
    }

    virtual CjObject *operator() (CjObject *a, CjObject *b)
    {
        I *t = new T(b);
        t = dynamic_cast<I *>(t->cons(a));
        return invoke(t);
    }

    virtual CjObject *operator() (CjObject *a, CjObject *b, CjObject *c)
    {
        I *t = new T(c);
        t = dynamic_cast<I *>(t->cons(b)->cons(a));
        return invoke(t);
    }

    virtual CjObject *operator() (CjObject *a, CjObject *b, CjObject *c, CjObject *d)
    {
        I *t = new T(d);
        t = dynamic_cast<I *>(t->cons(c)->cons(b)->cons(a));
        return invoke(t);
    }


/*    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d, CjObject *e);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d, CjObject *e, CjObject *f);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d, CjObject *e, CjObject *f, CjObject *g);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d, CjObject *e, CjObject *f, CjObject *g, CjObject *h);
    virtual CjObject *doInvoke(CjObject *a, CjObject *b, CjObject *c, CjObject *d, CjObject *e, CjObject *f, CjObject *g, CjObject *h, CjObject *i);
*/
    //virtual CjObject *invoke(QSharedPointer<I> params) = 0;
    virtual CjObject *invoke(I * params) = 0;


};
}
#endif // AFN_H
